﻿using System;
using System.Collections.Generic;
using Moe.ECamel.Common.Contracts;
using Moe.ECamel.Common.Entities;
using Moe.ECamel.Server.BL;

namespace Moe.ECamel.Server.Services
{
	public class UserService : ECamelService, IUserService
	{
		public UserService()
			: base()
		{
			
		}

		public UserService(ECamelService caller)
			: base(caller)
		{

		}

		public User GetUser(String username, byte[] hashedPassword)
		{
			using (var bl = new UserBL(GetReadOnlyDataContext()))
			{
				var user = bl.GetUserByUsername(username);
				// If no such user, login failed - abort:
				if (user == null)
					return null;
				// If password is incorrect, login failed - abort:
				if (!AreEqual(user.HashedPassword, hashedPassword))
					return null;

				return user;
			}
		}
		public ECamelError CreateUser(User user)
		{
			ECamelError error;

			using (var bl = new UserBL(GetReadWriteDataContext()))
			{
				error = bl.CreateUser(user);
			}

			return SubmitChanges(error);
		}
		public ECamelError UpdateUser(User user)
		{
			ECamelError error;

			using (var bl = new UserBL(GetReadWriteDataContext()))
			{
				error = bl.UpdateUser(user);
			}

			return SubmitChanges(error);
		}
		public ECamelError ChangeUserPassword(int userId, byte[] oldPassword, byte[] newPassword)
		{
			using (var bl = new UserBL(GetReadWriteDataContext()))
			{
				// Get user:
				var user = bl.GetUserById(userId);
				// Verify old password matches.
				if (!AreEqual(user.HashedPassword, oldPassword))
					return new ECamelError(MessageIds.ChangePasswordFailedInvalidOldPassword);

				user.HashedPassword = newPassword;
			}

			SubmitChanges();
			return null;
		}

		public IList<Operation> GetUserOperations(int userId)
		{
			using (var bl = new UserBL(GetReadOnlyDataContext()))
			{
				return bl.GetUserOperations(userId);
			}
		}

		private static bool AreEqual<T>(T[] array1, T[] array2)
		{
			// If are same, naturally are equal:
			if (array1 == array2)
				return true;

			// If either is null or length is not the same, return false:
			if (array1 == null || array2 == null || array1.Length != array2.Length)
				return false;

			// Check each array item for equality:
			for (int i = 0; i < array1.Length; i++)
				if (!Equals(array1[i], array2[i]))
					return false;

			return true;
		}
	}
}
